package com.easychat.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import com.easychat.entity.dto.MessageSendDto;
import com.easychat.entity.dto.SysSettingDto;
import com.easychat.entity.dto.TokenUserInfoDto;
import com.easychat.entity.enums.*;
import com.easychat.entity.po.*;
import com.easychat.entity.query.*;
import com.easychat.exception.BusinessException;
import com.easychat.mappers.GroupInfoMapper;
import com.easychat.mappers.UserContactMapper;
import com.easychat.mappers.UserInfoMapper;
import com.easychat.redis.RedisComponent;
import com.easychat.service.UserContactService;
import com.easychat.websocket.netty.MessageHandler;
import jodd.util.ArraysUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.easychat.entity.vo.PaginationResultVO;
import com.easychat.mappers.UserContactApplyMapper;
import com.easychat.service.UserContactApplyService;
import com.easychat.utils.StringTools;
import org.springframework.transaction.annotation.Transactional;


/**
 * 好友申请表 业务接口实现
 */
@Service("userContactApplyService")
public class UserContactApplyServiceImpl implements UserContactApplyService {

    @Resource
    private UserContactApplyMapper<UserContactApply, UserContactApplyQuery> userContactApplyMapper;
    @Resource
    private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;
    @Resource
    private UserContactMapper<UserContact, UserContactQuery> userContactMapper;
    @Resource
    private GroupInfoMapper<GroupInfo, GroupInfoQuery> groupInfoMapper;
    @Resource
    private RedisComponent redisComponent;
    @Resource
    private UserContactService userContactService;
    @Resource
    private MessageHandler messageHandler;

    private static final Logger logger = LoggerFactory.getLogger(UserContactApplyServiceImpl.class);


    /**
     * 根据条件查询列表
     */
    @Override
    public List<UserContactApply> findListByParam(UserContactApplyQuery param) {
        return this.userContactApplyMapper.selectList(param);
    }

    /**
     * 根据条件查询列表
     */
    @Override
    public Integer findCountByParam(UserContactApplyQuery param) {
        return this.userContactApplyMapper.selectCount(param);
    }

    /**
     * 分页查询方法
     */
    @Override
    public PaginationResultVO<UserContactApply> findListByPage(UserContactApplyQuery param) {
        int count = this.findCountByParam(param);
        int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

        SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
        param.setSimplePage(page);
        List<UserContactApply> list = this.findListByParam(param);
        PaginationResultVO<UserContactApply> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
        return result;
    }

    /**
     * 新增
     */
    @Override
    public Integer add(UserContactApply bean) {
        return this.userContactApplyMapper.insert(bean);
    }

    /**
     * 批量新增
     */
    @Override
    public Integer addBatch(List<UserContactApply> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.userContactApplyMapper.insertBatch(listBean);
    }

    /**
     * 批量新增或者修改
     */
    @Override
    public Integer addOrUpdateBatch(List<UserContactApply> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.userContactApplyMapper.insertOrUpdateBatch(listBean);
    }

    /**
     * 多条件更新
     */
    @Override
    public Integer updateByParam(UserContactApply bean, UserContactApplyQuery param) {
        StringTools.checkParam(param);
        return this.userContactApplyMapper.updateByParam(bean, param);
    }

    /**
     * 多条件删除
     */
    @Override
    public Integer deleteByParam(UserContactApplyQuery param) {
        StringTools.checkParam(param);
        return this.userContactApplyMapper.deleteByParam(param);
    }

    /**
     * 根据ApplyId获取对象
     */
    @Override
    public UserContactApply getUserContactApplyByApplyId(Integer applyId) {
        return this.userContactApplyMapper.selectByApplyId(applyId);
    }

    /**
     * 根据ApplyId修改
     */
    @Override
    public Integer updateUserContactApplyByApplyId(UserContactApply bean, Integer applyId) {
        return this.userContactApplyMapper.updateByApplyId(bean, applyId);
    }

    /**
     * 根据ApplyId删除
     */
    @Override
    public Integer deleteUserContactApplyByApplyId(Integer applyId) {
        return this.userContactApplyMapper.deleteByApplyId(applyId);
    }

    /**
     * 根据ApplyUserIdAndReceiveUserIdAndContactId获取对象
     */
    @Override
    public UserContactApply getUserContactApplyByApplyUserIdAndReceiveUserIdAndContactId(String applyUserId, String receiveUserId, String contactId) {
        return this.userContactApplyMapper.selectByApplyUserIdAndReceiveUserIdAndContactId(applyUserId, receiveUserId, contactId);
    }

    /**
     * 根据ApplyUserIdAndReceiveUserIdAndContactId修改
     */
    @Override
    public Integer updateUserContactApplyByApplyUserIdAndReceiveUserIdAndContactId(UserContactApply bean, String applyUserId, String receiveUserId, String contactId) {
        return this.userContactApplyMapper.updateByApplyUserIdAndReceiveUserIdAndContactId(bean, applyUserId, receiveUserId, contactId);
    }

    /**
     * 根据ApplyUserIdAndReceiveUserIdAndContactId删除
     */
    @Override
    public Integer deleteUserContactApplyByApplyUserIdAndReceiveUserIdAndContactId(String applyUserId, String receiveUserId, String contactId) {
        return this.userContactApplyMapper.deleteByApplyUserIdAndReceiveUserIdAndContactId(applyUserId, receiveUserId, contactId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer applyAdd(TokenUserInfoDto tokenUserInfo, String contactId, String applyInfo) {
        Date curTime = new Date();
        UserContactTypeEnum typeEnum = UserContactTypeEnum.getByPrefix(contactId.substring(0, 1));
        if (typeEnum == null) {
            throw new BusinessException("非法联系人");
        }
        applyInfo = applyInfo == null ? "" : applyInfo;

        //如果是被拉黑
        UserContact userContact = userContactMapper.selectByUserIdAndContactId(tokenUserInfo.getUserId(), contactId);
        if (userContact != null
                &&
                ArraysUtil.contains(
                        new Integer[]{
                                UserContactStatusEnum.BLACK_BE.getCode(),
                                UserContactStatusEnum.BLACK_BE_FIRST.getCode()
                        }, userContact.getStatus()
                )
        ) {
            throw new BusinessException("已被对方拉黑，无法申请好友");
        }

        Integer joinType = null;//加入类型
        String receiverId = null;//接收者id
        //如果是群
        if (UserContactTypeEnum.GROUP == typeEnum) {
            GroupInfo groupInfo = groupInfoMapper.selectByGroupId(contactId);
            //如果群已解散，无法申请
            if (groupInfo == null || GroupStatusEnum.DELETED.getCode().equals(groupInfo.getStatus())) {
                throw new BusinessException("群不存在或已经被解散，无法申请");
            }
            receiverId = groupInfo.getGroupOwnerId();
            joinType = groupInfo.getJoinType();
        } else {//如果是好友
            UserInfo userInfo = userInfoMapper.selectByUserId(contactId);
            if (userInfo == null) {
                throw new BusinessException("用户不存在");
            }
            receiverId = userInfo.getUserId();
            joinType = userInfo.getJoinType();
        }
        if (JoinTypeEnum.JOIN.getType().equals(joinType)) {
            userContactService.addContact(tokenUserInfo.getUserId(), receiverId, contactId, typeEnum.getType(), applyInfo);
            return joinType;
        }

        UserContactApply contactApply = userContactApplyMapper.selectByApplyUserIdAndReceiveUserIdAndContactId(tokenUserInfo.getUserId(), receiverId, contactId);
        //如果申请表中已存在该申请， 用户重复申请，执行update
        if (contactApply != null) {

            UserContactApply userContactApply = new UserContactApply();
            userContactApply.setLastApplyTime(curTime.getTime());
            userContactApply.setReceiveUserId(receiverId);
            userContactApply.setApplyInfo(applyInfo);
            userContactApply.setStatus(UserContactApplyStatusEnum.INIT.getStatus());
            userContactApplyMapper.updateByApplyUserIdAndReceiveUserIdAndContactId(userContactApply, tokenUserInfo.getUserId(), receiverId, contactId);
        } else {//如果是第一次申请，执行insert

            UserContactApply userContactApply = new UserContactApply();
            userContactApply.setApplyUserId(tokenUserInfo.getUserId());
            userContactApply.setReceiveUserId(receiverId);
            userContactApply.setContactType(typeEnum.getType());
            userContactApply.setContactId(contactId);
            userContactApply.setApplyInfo(applyInfo);
            userContactApply.setStatus(UserContactApplyStatusEnum.INIT.getStatus());
            userContactApply.setLastApplyTime(curTime.getTime());
            userContactApplyMapper.insert(userContactApply);
        }

        //给申请人通知 ，当第一次申请，或者 申请状态为其他状态
        if (contactApply == null || !UserContactApplyStatusEnum.INIT.getStatus().equals(contactApply.getStatus())) {
            //  给申请人发送ws通知
            MessageSendDto messageSendDto = new MessageSendDto();
            messageSendDto.setMessageType(MessageTypeEnum.CONTACT_APPLY.getType());
            messageSendDto.setMessageContent(applyInfo);
            messageSendDto.setContactId(contactId);
            messageHandler.sendMessage(messageSendDto);

        }

        return joinType;
    }

    @Override
    public void dealWithApply(String userId, Integer applyId, Integer status) {
        UserContactApplyStatusEnum statusEnum = UserContactApplyStatusEnum.getByStatus(status);

        if (statusEnum == null || UserContactApplyStatusEnum.INIT.getStatus() == status) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        //检验 处理申请的人 和 申请中的接收者 是否为一个
        //防止恶意修改
        UserContactApply applyInfo = userContactApplyMapper.selectByApplyId(applyId);
        if (!applyInfo.getReceiveUserId().equals(userId)) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        UserContactApply userContactApply = new UserContactApply();
        userContactApply.setStatus(statusEnum.getStatus());
        userContactApply.setLastApplyTime(new Date().getTime());


        //加入 “乐观锁” 防止并发问题:  查找到状态为‘待处理’的记录。
        UserContactApplyQuery userContactApplyQuery = new UserContactApplyQuery();
        userContactApplyQuery.setStatus(UserContactApplyStatusEnum.INIT.getStatus());
        userContactApplyQuery.setApplyId(applyId);

        Integer count = userContactApplyMapper.updateByParam(userContactApply, userContactApplyQuery);
        //修改失败
        if (count == 0) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }


        //修改成功后，如果是 ‘已同意’状态，需要把联系人信息添加到联系人列表中
        if (UserContactApplyStatusEnum.PASS.getStatus().equals(status)) {
            //添加联系人
            userContactService.addContact(applyInfo.getApplyUserId(), applyInfo.getReceiveUserId(), applyInfo.getContactId(), applyInfo.getContactType(), applyInfo.getApplyInfo());
            return;
        }
        //如果是拉黑
        if (UserContactApplyStatusEnum.BLACK.getStatus().equals(status)) {
            Date curdDate = new Date();
            //1.修改 UserContact 表
            UserContact userContact = new UserContact();
            userContact.setLastUpdateTime(curdDate);
            userContact.setStatus(UserContactStatusEnum.BLACK_BE_FIRST.getCode());
            userContact.setUserId(applyInfo.getApplyUserId());
            userContact.setContactId(applyInfo.getContactId());
            userContact.setContactType(applyInfo.getContactType());
            //可能之前就存在好友关系，数据库中存在记录，所以可能是修改
            //修改的话xml中只设置了允许修改 status lastUpdateTime 2个字段
            userContactMapper.insertOrUpdate(userContact);
        }

    }

}